#include "ParticleManager.h"
#include "../TinyXML/tinyxml.h"
#include "../SGD Wrappers/SGD_GraphicsManager.h"

ParticleManager* ParticleManager::GetInstance()
{
	static ParticleManager instance;
	return &instance;
}

ParticleManager::ParticleManager()
{
}


ParticleManager::~ParticleManager()
{
	
}

bool ParticleManager::LoadEmitter(string FileName)
{
	SGD::GraphicsManager*graph = SGD::GraphicsManager::GetInstance();
	TiXmlDocument doc;
	doc.LoadFile(FileName.c_str());
	TiXmlElement*root = doc.RootElement();
	TiXmlElement*filename = root->FirstChildElement();
	const char* fname = filename->GetText();
	//TiXmlText*name = filename->ToText();
	TiXmlElement*particle = filename->NextSiblingElement();
	string pname = particle->Attribute("Name");
	const char* loop = particle->Attribute("IsLooping");
	const char*burst = particle->Attribute("Bursting");
	TiXmlElement*emitter = particle->FirstChildElement();
	TiXmlElement*shape = emitter->FirstChildElement();
	int s;
	shape->Attribute("shape", &s);
	TiXmlElement*pos = shape->NextSiblingElement();
	Emitter load;
	string lfname = "resources/images/";
	lfname+= fname;
	load.Flyweight.image = graph->LoadTexture(lfname.c_str());
	load.EmitterShape = (EShape)s;
	if (!strcmp(loop,"true"))
		load.looping = true;
	else
		load.looping = false;
	if (!strcmp(burst, "true"))
		load.bursting = true;
	else
		load.bursting = false;
	double help;
	pos->Attribute("x", &help);
	load.Position.x = (float)help;
	pos->Attribute("y", &help);
	load.Position.y = (float)help;
	TiXmlElement*size = pos->NextSiblingElement();
	size->Attribute("width", &help);
	load.Size.width = (float)help;
	size->Attribute("height", &help);
	load.Size.height = (float)help;
	TiXmlElement*num = size->NextSiblingElement();
	num->Attribute("num", &load.NumParticles);
	TiXmlElement*spawn = num->NextSiblingElement();
	spawn->Attribute("rate", &help);
	load.SpawnRate = (float)help;
	TiXmlElement*spread = spawn->NextSiblingElement();
	spread->Attribute("s", &help);
	load.Spread = (float)help;
	TiXmlElement*gravity = spread->NextSiblingElement();
	const char*t = gravity->Attribute("Grav");
	if (!strcmp(t, "true"))
		load.gravity = true;
	else
		load.gravity = false;
	gravity->Attribute("pull",&help);
	load.gravpull = (float)help;
	gravity->Attribute("x",&help);
	load.gravpos.x = (float)help;
	gravity->Attribute("y", &help);
	load.gravpos.y = (float)help;

	TiXmlElement*fly = emitter->NextSiblingElement();
	TiXmlElement*Life = fly->FirstChildElement();
	Life->Attribute("min", &help);
	load.Flyweight.MinLife = (float)help;
	Life->Attribute("max", &help);
	load.Flyweight.MaxLife = (float)help;
	TiXmlElement*Color = Life->NextSiblingElement();
	Color->Attribute("SA", &help);
	load.Flyweight.ColorStartA = (int)help;
	Color->Attribute("SR", &help);
	load.Flyweight.ColorStartR = (int)help;
	Color->Attribute("SG", &help);
	load.Flyweight.ColorStartG = (int)help;
	Color->Attribute("SB", &help);
	load.Flyweight.ColorStartB = (int)help;
	Color->Attribute("EA", &help);
	load.Flyweight.ColorEndA = (int)help;
	Color->Attribute("ER", &help);
	load.Flyweight.ColorEndR = (int)help;
	Color->Attribute("EG", &help);
	load.Flyweight.ColorEndG = (int)help;
	Color->Attribute("EB", &help);
	load.Flyweight.ColorEndB = (int)help;
	TiXmlElement*rot = Color->NextSiblingElement();
	rot->Attribute("start", &help);
	load.Flyweight.RotationStart = (float)help;
	rot->Attribute("change", &help);
	load.Flyweight.RotationChange = (float)help;
	TiXmlElement*scale = rot->NextSiblingElement();
	scale->Attribute("sw", &help);
	load.Flyweight.ScaleStart.width = (float)help;
	scale->Attribute("sh", &help);
	load.Flyweight.ScaleStart.height = (float)help;
	scale->Attribute("cw", &help);
	load.Flyweight.ScaleChange.width = (float)help;
	scale->Attribute("ch", &help);
	load.Flyweight.ScaleChange.height = (float)help;
	TiXmlElement*vel = scale->NextSiblingElement();
	vel->Attribute("sx", &help);
	load.Flyweight.VelocityStart.x = (float)help;
	vel->Attribute("sy", &help);
	load.Flyweight.VelocityStart.y = (float)help;
	vel->Attribute("cx", &help);
	load.Flyweight.VelocityChange.x = (float)help;
	vel->Attribute("cy", &help);
	load.Flyweight.VelocityChange.y = (float)help;
	LoadedEmitters[pname] = load;
	return true;
}
bool ParticleManager::UnloadEmitter(string EmitterName)
{
	SGD::GraphicsManager::GetInstance()->UnloadTexture(LoadedEmitters[EmitterName].Flyweight.image);
	LoadedEmitters.erase(EmitterName);
	return true;
}
int ParticleManager::CreateEmitter(string EmitterName,Entity*owner)
{
	ActiveEmitters.push_back(LoadedEmitters[EmitterName]);
	ActiveEmitters.back().owner = owner;
	ActiveEmitters.back().EmitterID = (ActiveEmitters.back().EmitterID << 7) + atoi(EmitterName.c_str()) + (ActiveEmitters.back().EmitterID >> 3) + ActiveEmitters.size();
	ActiveEmitters.back().Init();
	return ActiveEmitters.back().EmitterID;
}
bool ParticleManager::FreeEmitter(int EmitterID)
{
	std::list<Emitter>::iterator iter = ActiveEmitters.begin();
	for (; iter != ActiveEmitters.end(); iter++)
	{
		if ((*iter).EmitterID == EmitterID)
		{
			ActiveEmitters.erase(iter);
			return true;
		}
	}
	return false;
}

bool ParticleManager::FreeAllEmitters()
{
	std::list<Emitter>::iterator iter = ActiveEmitters.begin();
	for (; iter != ActiveEmitters.end(); )
		iter = ActiveEmitters.erase(iter);
	return true;
}

std::list<Emitter>::iterator& ParticleManager::FreeEmitter(std::list<Emitter>::iterator& iter)
{
	static std::list<Emitter>::iterator temp = ActiveEmitters.erase(iter);
	return temp;
}

void ParticleManager::UpdateEmitter(float dt)
{
	std::list<Emitter>::iterator iter = ActiveEmitters.begin();
	for (; iter!=ActiveEmitters.end();)
	{
		(*iter).Update(dt);
		if ((*iter).Done())
			iter = FreeEmitter(iter);
		else
			iter++;
	}
}
void ParticleManager::RenderEmitter()
{
	std::list<Emitter>::iterator iter = ActiveEmitters.begin();
	for (; iter != ActiveEmitters.end(); iter++)
	{
		(*iter).Render();
	}
}